Day 13
I don't really have a title for this one, or much to say about part 1 in general.
fn reflection_score(map: &[&[u8]]) -> usize {
// Find reflection around a vertical line.
'outer: for x in 1..map[0].len() {
let dx = usize::min(x, map[0].len() - x);
for dx in 1..=dx {
for row in map {
if row[x - dx] != row[x + dx - 1] {
continue 'outer;
}
}
}
return x;
}
// Find reflection around a horizontal line.
'outer: for y in 1..map.len() {
let dy = usize::min(y, map.len() - y);
for dy in 1..=dy {
for x in 0..map[0].len() {
if map[y - dy][x] != map[y + dy - 1][x] {
continue 'outer;
}
}
}
return y * 100;
}
0
}
It's just about implementing the thing. My version is honestly kind of fiddly, but it works. I'm glad Rust has labelled loops, so I can continue
the 'outer
one.
Part 2 was really funny though. When you first read it, it sounds like you now need to like, idk. Try your part 1 code on every changed version of every map. But that sounds unreasonable.
No, all part 2 is saying is that the line we're looking for has to have one mistake in its reflection. So simply... keep track of whether there was a mistake!
fn smudged_reflection_score(map: &[&[u8]]) -> usize {
// Find reflection around a vertical line.
'outer: for x in 1..map[0].len() {
let mut mistake = false;
let dx = usize::min(x, map[0].len() - x);
for dx in 1..=dx {
for row in map {
if row[x - dx] != row[x + dx - 1] {
match mistake {
true => continue 'outer,
false => mistake = true,
}
}
}
}
if mistake {
return x;
}
}
// Find reflection around a horizontal line.
'outer: for y in 1..map.len() {
let mut mistake = false;
let dy = usize::min(y, map.len() - y);
for dy in 1..=dy {
for x in 0..map[0].len() {
if map[y - dy][x] != map[y + dy - 1][x] {
match mistake {
true => continue 'outer,
false => mistake = true,
}
}
}
}
if mistake {
return y * 100;
}
}
0
}
Straightforward modification of part 1. When we run into a mistake, just remember it; unless there was already one, in which case, nope out like before. Only return a score if mistake
is true, to avoid accidentally finding the part 1 reflection line again (part 2 is explicit that we want a different one).
Also, ignore the fact that I match bool
instead of if/else
. When both branches are one-liners, it looks neater to me.
Anyway, in the spirit of golfing a bit, I then combined both versions into one function:
fn reflection_score(map: &[&[u8]], smudged: bool) -> usize {
// Find reflection around a vertical line.
'outer: for x in 1..map[0].len() {
let mut mistake = !smudged;
let dx = usize::min(x, map[0].len() - x);
for dx in 1..=dx {
for row in map {
if row[x - dx] != row[x + dx - 1] {
match mistake {
true => continue 'outer,
false => mistake = true,
}
}
}
}
if mistake {
return x;
}
}
// Find reflection around a horizontal line.
'outer: for y in 1..map.len() {
let mut mistake = !smudged;
let dy = usize::min(y, map.len() - y);
for dy in 1..=dy {
for x in 0..map[0].len() {
if map[y - dy][x] != map[y + dy - 1][x] {
match mistake {
true => continue 'outer,
false => mistake = true,
}
}
}
}
if mistake {
return y * 100;
}
}
0
}
Just take the code from part 2, but, in part 1 mode, act as if we've already seen a mistake.
Pretty neat problem today, I think. And, other than the actual gnarly reflection finding, pretty neat solution from me, too.